#ifndef API_H
#define API_H

#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QUrl>
#include <QUrlQuery>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <QDebug>
#include <QTimer>
#include <QByteArray>
#include <QString>
#include <QStringConverter>  // 用于UTF-8编码
#include <functional>
#include <QSslConfiguration>  // HTTPS加密配置
#include <QFile>
#include <QFile>
#include <QFileInfo>

// 定义回调函数类型：参数为（是否成功，响应数据，错误信息）
typedef std::function<void(bool success, const QJsonObject& response, const QString& errorMsg, int SatusCode)> ApiCallback;

class Api {
private:
    static Api* m_instance;  // 静态实例
    QNetworkAccessManager* m_manager;  // 网络请求管理器（全局唯一）
    QString baseUrl = "http://localhost:8080";
    QString m_globalToken;  // 全局身份令牌（如JWT）

    Api();
    ~Api() = default;
    Api(const Api&) = delete;  // 禁止拷贝
    Api& operator=(const Api&) = delete;  // 禁止赋值

    // 通用请求发送函数（内部使用，封装重复逻辑）
    void sendRequest(const QString& url,
                     const QByteArray& method,
                     const QJsonObject& params,
                     int timeoutMs,
                     ApiCallback callback);

public:
    // 设置全局身份令牌（如登录后获取的Token）
    void setGlobalToken(const QString& token) {
        m_globalToken = token;

        saveToken();
    }

    void readToken() {
        const QString filePath = "token";
        QFile file(filePath);
        QFileInfo fileInfo(file);

        // 1. 如果文件不存在，自动创建空文件
        if (!fileInfo.exists()) {
            qWarning() << "token 文件不存在，自动创建空文件：" << filePath;

            // 创建文件（使用 WriteOnly + Truncate 模式，若文件不存在则创建）
            if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text)) {
                qCritical() << "创建 token 文件失败：" << file.errorString();
                return; // 创建失败直接返回，避免后续操作报错
            }
            file.close(); // 创建空文件后关闭
            m_globalToken.clear(); // 空文件对应空 Token
            return;
        }

        // 2. 文件存在，尝试打开并读取
        if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
            qCritical() << "打开 token 文件失败：" << file.errorString();
            m_globalToken.clear();
            return;
        }

        // 3. 读取 Token（UTF-8 编码）
        QTextStream in(&file);
        m_globalToken = in.readLine().trimmed(); // trimmed() 去除首尾空格/换行符

        file.close();
        qInfo() << "Token 读取成功：" << (m_globalToken.isEmpty() ? "空" : m_globalToken);
    }

    void saveToken() {
        const QString filePath = "token";
        QFile file(filePath);

        // 打开文件（不存在则创建，存在则覆盖）
        if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text)) {
            qCritical() << "保存 Token 失败：" << file.errorString();
            return;
        }

        // 写入 Token（UTF-8 编码）
        QTextStream out(&file);
        out << m_globalToken; // 写入原始 Token（无额外空格）

        file.close();
        qInfo() << "Token 保存成功：" << m_globalToken;
    }

    QString getToken() const {
        return m_globalToken;
    }

    static Api* getInstance();

    void get(const QString& url, const QJsonObject& params = {}, int timeout = 5000, ApiCallback callback = nullptr);
    void post(const QString& url, const QJsonObject& params = {}, int timeout = 5000, ApiCallback callback = nullptr);
    void del(const QString& url, const QJsonObject& params = {}, int timeout = 5000, ApiCallback callback = nullptr);
    void put(const QString& url, const QJsonObject& params = {}, int timeout = 5000, ApiCallback callback = nullptr);

    void configureHttps(const QString& caCertPath = "");
};

#endif // API_H
